package net.lgy.config;


import io.netty.channel.ChannelOption;
import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.handler.timeout.WriteTimeoutHandler;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.netty.http.client.HttpClient;
import reactor.netty.resources.ConnectionProvider;

import java.time.Duration;
import java.util.concurrent.TimeUnit;

@Configuration
@Slf4j
@Data
@ConfigurationProperties(prefix = "stream")
public class WebClientConfig {
    private String baseUrl;

    private String chatStreamPath;

    /**
     * 超时配置
     */
    private Timeout timeout = new Timeout();

    /**
     * 连接池配置
     */
    private Pool pool = new Pool();

    /**
     * 超时配置内部类
     * 用于定义各种网络操作的超时时间配置
     */
    @Data
    public static class Timeout {
        /**
         * 连接超时时间
         */
        private Duration connect;

        /**
         * 响应超时时间
         */
        private Duration response;

        /**
         * 读取超时时间
         */
        private Duration read;

        /**
         * 写入超时时间
         */
        private Duration write;
    }

    /**
     * 连接池配置内部类
     * 用于定义HTTP连接池的相关配置参数
     */
    @Data
    public static class Pool {
        /**
         * 最大连接数
         */
        private int maxConnections;

        /**
         * 连接最大空闲时间
         */
        private Duration maxIdleTime;

        /**
         * 连接最大生存时间
         */
        private Duration maxLifeTime;

        /**
         * 获取连接的最长等待时间
         */
        private Duration pendingAcquireTimeout;

        /**
         * 后台清理连接的时间间隔
         */
        private Duration evictInBackground;
    }



    @Bean
    public WebClient webClient() {
        // 创建连接池
        ConnectionProvider provider = ConnectionProvider.builder("stream-connection-pool")
                .maxConnections(pool.getMaxConnections())
                .maxIdleTime(pool.getMaxIdleTime())
                .maxLifeTime(pool.getMaxLifeTime())
                .pendingAcquireTimeout(pool.getPendingAcquireTimeout())
                .evictInBackground(pool.getEvictInBackground())
                .build();

        // 配置 HttpClient
        HttpClient httpClient = HttpClient.create(provider)
                .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, (int) timeout.getConnect().toMillis())
                .responseTimeout(timeout.getResponse())
                .doOnConnected(conn -> conn
                        .addHandlerLast(new ReadTimeoutHandler(timeout.getRead().getSeconds(), TimeUnit.SECONDS))
                        .addHandlerLast(new WriteTimeoutHandler(timeout.getWrite().getSeconds(), TimeUnit.SECONDS))
                );

        // 创建 WebClient
        return WebClient.builder()
                .baseUrl(baseUrl)
                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                .defaultHeader(HttpHeaders.ACCEPT, MediaType.TEXT_EVENT_STREAM_VALUE)
                .clientConnector(new ReactorClientHttpConnector(httpClient))
                .build();
    }
}


